<html>
<head><meta charset="utf-8"><title>The `Stream::next()` problem · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html">The `Stream::next()` problem</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="221324669"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221324669" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221324669">(Dec 31 2020 at 23:35)</a>:</h4>
<p>I wrote up a note on the problem we're facing in the Stream RFC: <a href="https://hackmd.io/@CTI_5_5PSN2-6VHLeF5YuQ/r1Af46oaD/edit">The <code>Stream::next()</code> problem</a></p>
<p>In short, we want to provide a <code>next</code> method on the trait itself, since that's what everyone will use. But the method signature mentions <code>Self</code>, which means it won't work on trait objects. There is a perfectly reasonable method dispatch path that the language _could_ take instead for trait objects, but doesn't.</p>



<a name="221324825"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221324825" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221324825">(Dec 31 2020 at 23:39)</a>:</h4>
<p>I list a few different solutions in the doc, though I'm probably missing some.</p>



<a name="221324876"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221324876" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221324876">(Dec 31 2020 at 23:40)</a>:</h4>
<p>I think this could be a chance to improve usability of trait objects.</p>



<a name="221345627"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221345627" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221345627">(Jan 01 2021 at 10:12)</a>:</h4>
<p>about "Object-safe <code>Self</code>"</p>



<a name="221345640"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221345640" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221345640">(Jan 01 2021 at 10:13)</a>:</h4>
<p>could we theoretically allow self exactly if <code>CoerceUnsized</code> can be applied to all uses of <code>Self</code>?</p>



<a name="221345685"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221345685" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221345685">(Jan 01 2021 at 10:14)</a>:</h4>
<p>so for <code>Stream::next</code> this would be fine as <code>Next&lt;Foo&gt;</code> can be coerced to <code>Next&lt;dyn Stream&gt;</code> <span aria-label="thinking" class="emoji emoji-1f914" role="img" title="thinking">:thinking:</span></p>



<a name="221345704"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221345704" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221345704">(Jan 01 2021 at 10:15)</a>:</h4>
<p>this should be fairly straighforward to implement though I am a bit worried that there is code which relies on uses of <code>Self</code> to not be object safe</p>



<a name="221345824"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221345824" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> lcnr <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221345824">(Jan 01 2021 at 10:18)</a>:</h4>
<p>dispatch on <code>Self: Sized</code> also seems like a nice solution to me</p>



<a name="221365598"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221365598" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221365598">(Jan 01 2021 at 19:42)</a>:</h4>
<p>The main workaround currently available is something along these lines:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">/// Have the following trait be a super trait of `Stream`.</span>
<span class="k">pub</span><span class="w"></span>
<span class="k">trait</span><span class="w"> </span><span class="n">DynNext</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">dyn_next</span><span class="o">&lt;'</span><span class="na">slf</span><span class="o">&gt;</span><span class="w"> </span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="nb">_</span> <span class="nc">mut</span><span class="w"> </span><span class="bp">Self</span><span class="p">)</span><span class="w"></span>
<span class="w">      </span>-&gt; <span class="nc">Next</span><span class="o">&lt;'</span><span class="nb">_</span><span class="p">,</span><span class="w"> </span><span class="k">dyn</span><span class="w"> </span><span class="o">'</span><span class="na">slf</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Stream</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Unpin</span><span class="o">&gt;</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span>: <span class="o">'</span><span class="na">slf</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="o">&lt;</span><span class="n">T</span><span class="w"> </span>: <span class="nc">Stream</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Unpin</span><span class="o">&gt;</span><span class="w"> </span><span class="n">DynNext</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">dyn_next</span><span class="o">&lt;'</span><span class="na">slf</span><span class="o">&gt;</span><span class="w"> </span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="nb">_</span> <span class="nc">mut</span><span class="w"> </span><span class="bp">Self</span><span class="p">)</span><span class="w"></span>
<span class="w">      </span>-&gt; <span class="nc">Next</span><span class="o">&lt;'</span><span class="nb">_</span><span class="p">,</span><span class="w"> </span><span class="k">dyn</span><span class="w"> </span><span class="o">'</span><span class="na">slf</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">Stream</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">Unpin</span><span class="o">&gt;</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span>: <span class="o">'</span><span class="na">slf</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">Next</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>so that trait objects can use <code>.dyn_next()</code> (<a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=3291ef11e1dd420fdabe04884edfa23c">Playground</a>)</p>
<hr>
<p>Note that with this approach it's adding an associated type that becomes challenging: we easily stumble upon cycle detected when writing things like <code>Stream : DynNext&lt;Self::Item&gt;</code>, leading to the supertrait hierarchy needing to be inverted so that  <code>Self::Item</code> is available to <code>DynNext</code>.<br>
This, in turn, leads to an associated <code>fn dyn_next</code> helper method on <code>Stream</code> (since the initial objective is not to require a helper trait in scope), which happens not to be object-safe!</p>
<p>Basically,</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">trait</span><span class="w"> </span><span class="n">Whatever</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">id</span><span class="w"> </span><span class="p">(</span><span class="bp">self</span>: <span class="kp">&amp;</span><span class="o">'</span><span class="nb">_</span> <span class="nc">Self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="kp">&amp;</span><span class="o">'</span><span class="nb">_</span> <span class="p">(</span><span class="k">dyn</span><span class="w"> </span><span class="n">Whatever</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">AutoTrait</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="bp">Self</span><span class="w"> </span>: <span class="nc">AutoTrait</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>is not object-safe; and I fail to see why (<code>dyn Whatever</code> wouldn't be able to call <code>.id()</code>, but <code>dyn Whatever + AutoTrait</code> would). If something needs to be changed or improved, then this auto trait situation is definitely it! Since <code>where Self : 'lifetime</code> bounds are already supported, and since lifetimes and auto-traits behave very similarly with trait objects, I think the "do not mention <code>Self</code> in the <code>where</code> clauses" rule should <strong>also</strong> make an exception for auto traits.</p>



<a name="221373965"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221373965" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221373965">(Jan 01 2021 at 23:16)</a>:</h4>
<p>I'm not sure I follow the second part of your comment, the <code>dyn_next</code> method you wrote can be placed on Stream directly and it remains object safe</p>



<a name="221374025"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221374025" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221374025">(Jan 01 2021 at 23:18)</a>:</h4>
<p>The private supertrait pattern is useful for adding helper methods that can't be overridden (and TIL you could write <code>impl&lt;T: SubTrait&gt; SuperTrait for T {}</code>)</p>



<a name="221374319"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221374319" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221374319">(Jan 01 2021 at 23:26)</a>:</h4>
<p>ideally we don't need a <code>dyn_next()</code> and can always use <code>next()</code>, but that could be an acceptable interim solution</p>



<a name="221374342"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221374342" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221374342">(Jan 01 2021 at 23:27)</a>:</h4>
<p>I can't think of cases where you would actually <em>want</em> <code>dyn_next()</code> if we were to solve this later, though</p>



<a name="221374397"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221374397" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221374397">(Jan 01 2021 at 23:28)</a>:</h4>
<p>since for <code>T: Stream + Unpin</code>, <code>Next&lt;'_, T&gt;</code> should coerce to <code>Next&lt;'_, dyn Stream + Unpin&gt;</code></p>



<a name="221374407"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221374407" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> tmandry <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221374407">(Jan 01 2021 at 23:29)</a>:</h4>
<p><span class="user-mention silent" data-user-id="216206">lcnr</span> <a href="#narrow/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem/near/221345640">said</a>:</p>
<blockquote>
<p>could we theoretically allow self exactly if <code>CoerceUnsized</code> can be applied to all uses of <code>Self</code>?</p>
</blockquote>
<p>Yeah this does seem promising, it would have a huge impact on the usability of trait objects imo</p>



<a name="221386669"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/The%20%60Stream%3A%3Anext%28%29%60%20problem/near/221386669" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Quy Nguyen <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem.html#221386669">(Jan 02 2021 at 06:19)</a>:</h4>
<p><span class="user-mention silent" data-user-id="216206">lcnr</span> <a href="#narrow/stream/213817-t-lang/topic/The.20.60Stream.3A.3Anext().60.20problem/near/221345704">said</a>:</p>
<blockquote>
<p>this should be fairly straighforward to implement though I am a bit worried that there is code which relies on uses of <code>Self</code> to not be object safe</p>
</blockquote>
<p>If the feature is shipped this year, there's always the idea of opting into dynamic dispatch that's been thrown around recently, so it wouldn't be a big deal.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>